﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows;
using System.Collections.Specialized;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Globalization;

namespace Frontend
{
    class TodoGrid: BorderedGrid
    {
        public ObservableCollection<Speakup.Class> Classes = new ObservableCollection<Speakup.Class>();

        enum ColumnId { Index, Name, DateTime, Remove, Done };

        Dictionary<Speakup.Class, bool> DoneDictionary = new Dictionary<Speakup.Class, bool>();

        public TodoGrid()
        {
            Classes.CollectionChanged += ClassesCollectionChanged;

            Dictionary<ColumnId, GridLength> columnWidths = new Dictionary<ColumnId, GridLength>();
            columnWidths.Add(ColumnId.Index, GridLength.Auto);
            columnWidths.Add(ColumnId.Remove, GridLength.Auto);
            columnWidths.Add(ColumnId.Done, GridLength.Auto);
            
            foreach (ColumnId value in Enum.GetValues(typeof(ColumnId)))
            {
                ColumnDefinition coldef = new ColumnDefinition();

                if (columnWidths.Keys.Contains(value))
                {
                    coldef.Width = columnWidths[value];
                }
                this.ColumnDefinitions.Add(coldef);
            }

            AddHeader();
        }

        void SetColumnName(ColumnId id, string name)
        {
            TextBlock txt = new TextBlock();
            txt.Text = name;
            txt.HorizontalAlignment = HorizontalAlignment.Center;

            int iid = (int)id;
            Grid.SetColumn(txt, (int)id);
            Grid.SetRow(txt, 0);
            this.Children.Add(txt);
        }

        void AddHeader()
        {
            RowDefinition rowdef = new RowDefinition();
            rowdef.Height = GridLength.Auto;

            RowDefinitions.Add(rowdef);

            SetColumnName(ColumnId.Index, "#");
            SetColumnName(ColumnId.Name, "Name");
            SetColumnName(ColumnId.DateTime, "Time");
            SetColumnName(ColumnId.Remove, "Remove?");
            SetColumnName(ColumnId.Done, "Changes done online?");
        }

        void AddClass(Speakup.Class speakupClass)
        {
            int index = RowDefinitions.Count;

            RowDefinition row = new RowDefinition();
            this.RowDefinitions.Add(row);

            string name = speakupClass.ClassName.FullName;


            string date = speakupClass.ClassTime.Date.ToString("MMM d yyyy", CultureInfo.InvariantCulture);
            DateTime beginTime = new DateTime(speakupClass.ClassTime.Begin.Ticks);
            DateTime endTime = new DateTime(speakupClass.ClassTime.End.Ticks);

            string fullDate = date + " " + beginTime.ToString("HH:mm") + " - " + endTime.ToString("HH:mm");


            //create controls
            TextBlock indexTxt = new TextBlock();
            indexTxt.Text = index.ToString();
            indexTxt.HorizontalAlignment = HorizontalAlignment.Center;

            DockPanel namePanel = new DockPanel();
            TextBlock nameTxt = new TextBlock();
            {
                
                nameTxt.Text = name;
                nameTxt.HorizontalAlignment = HorizontalAlignment.Center;

                TextBlock hyperlinkText = new TextBlock();

                Hyperlink copyLink = new Hyperlink(new Run("(copy)"));
                copyLink.Click += (a, b) => { Clipboard.SetData(DataFormats.Text, (Object)name); };

                hyperlinkText.Inlines.Add(copyLink);
                DockPanel.SetDock(hyperlinkText, Dock.Right);

                namePanel.Children.Add(hyperlinkText);
                namePanel.Children.Add(nameTxt);

            }

            DockPanel datePanel = new DockPanel();
            TextBlock dateTxt = new TextBlock();
            {               
                dateTxt.Text = fullDate;
                dateTxt.HorizontalAlignment = HorizontalAlignment.Center;

                TextBlock hyperlinkText = new TextBlock();

                Hyperlink copyLink = new Hyperlink(new Run("(copy)"));
                copyLink.Click += (a, b) => { Clipboard.SetData(DataFormats.Text, (Object)fullDate); };

                hyperlinkText.Inlines.Add(copyLink);
                DockPanel.SetDock(hyperlinkText, Dock.Right);

                datePanel.Children.Add(hyperlinkText);
                datePanel.Children.Add(dateTxt);
            }

            Button removeButton = new Button();
            removeButton.IsDefault = false;
            removeButton.Content = "Remove";
            removeButton.Click += (s, e) => { speakupClass.RestoreStatus(); };

            CheckBox doneCheckbox = new CheckBox();
            doneCheckbox.HorizontalAlignment = HorizontalAlignment.Center;
            doneCheckbox.VerticalAlignment = VerticalAlignment.Center;

            RoutedEventHandler handler = (s, e) =>
            {
                double opacity = 1;
                removeButton.IsEnabled = true;
                if (doneCheckbox.IsChecked == true)
                {
                    opacity = 0.3;
                    removeButton.IsEnabled = false;
                }

                if (DoneDictionary.Keys.Contains(speakupClass))
                {
                    DoneDictionary[speakupClass] = doneCheckbox.IsChecked ?? false;
                }

                namePanel.IsEnabled = !doneCheckbox.IsChecked ?? false;

                List<TextBlock> ctrls = new List<TextBlock> { indexTxt, nameTxt, dateTxt };
                foreach (TextBlock element in ctrls)
                {
                    Brush br = element.Foreground.Clone();
                    br.Opacity = opacity;
                    element.Foreground = br;
                }
            };

            doneCheckbox.Checked += handler;
            doneCheckbox.Unchecked += handler;

            if (DoneDictionary.Keys.Contains(speakupClass))
            {
                if (DoneDictionary[speakupClass])
                {
                    doneCheckbox.IsChecked = true;
                }
            }

            //add controls
            Grid.SetColumn(indexTxt, (int)ColumnId.Index);
            Grid.SetRow(indexTxt, index);
            this.Children.Add(indexTxt);

            Grid.SetColumn(namePanel, (int)ColumnId.Name);
            Grid.SetRow(namePanel, index);
            this.Children.Add(namePanel);

            Grid.SetColumn(datePanel, (int)ColumnId.DateTime);
            Grid.SetRow(datePanel, index);
            this.Children.Add(datePanel);

            Grid.SetColumn(removeButton, (int)ColumnId.Remove);
            Grid.SetRow(removeButton, index);
            this.Children.Add(removeButton);

            Grid.SetColumn(doneCheckbox, (int)ColumnId.Done);
            Grid.SetRow(doneCheckbox, index);
            this.Children.Add(doneCheckbox);
        }

        void RemoveUnmodified()
        {
            var forRemoval = from n in Classes
                             where n.IsStatusModified == false
                             select n;

            foreach (Speakup.Class speakupClass in forRemoval.ToList())
            {
                Classes.Remove(speakupClass);
            }
        }

        void UpdateGrid()
        {
            this.Children.Clear();
            this.RowDefinitions.Clear();


            var sortedClasses = from n in Classes
                                orderby n.ClassTime.Date + n.ClassTime.Begin                                
                                select n;

            AddHeader();
            foreach (Speakup.Class speakupClass in sortedClasses)
            {
                AddClass(speakupClass);
            }
        }

        void ClassesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                foreach (Speakup.Class speakupClass in e.NewItems)
                {
                    if (DoneDictionary.Keys.Contains(speakupClass) == false)
                    {
                        DoneDictionary[speakupClass] = false;
                    }
                }
            }
            else if(e.Action == NotifyCollectionChangedAction.Remove)
            {
                foreach (Speakup.Class speakupClass in e.OldItems)
                {
                    if (DoneDictionary.Keys.Contains(speakupClass) == false)
                    {
                        DoneDictionary.Remove(speakupClass);
                    }
                }
            }

            UpdateGrid();
        }
        
    }
}
